import Taro from '@tarojs/taro'
import { getCurrentInstance } from '@tarojs/runtime'
import { jsonParse } from './Helper'
import { getServerUrls,concatWithBaseUrl } from './ServerUrls'

// 刷新令牌的提前时间
export const LEAD_TIME = 3600 * 12

// TODO url 是否在白名单中
function inWhiteList(url) {
  // 请求白名单，不需要token
  const tokenWhiteList = [
    '/yz/v2/public/wechat/login',
    '/yz/v2/public/users/retrieve/password', // 忘记密码
    '/wechat/v1/pub/send_sms/not_auth',
    '/yz/v2/public/login', // 登录
    '/yz/v2/public/reg/sms', // 注册验证码
    '/yz/v2/public/reg', // 注册
    '/yz/v2/public/users/retrieve/password/sms', // 获取找回密码的验证码-V2
    '/yz/v2/public/wechat/getLoginToken', // 获取token
    '/talent/api/v1/enterprise/page', // 获取token
    '/talent/api/v1/enterprise/one',
    '/authx/api/v1/role/menu/tree', // 获取菜单列表
    '/talent/api/v1/supply-demand/page',
    '/talent/api/v1/supply-demand/one',
    '/talent/api/v1/policy/one',
    '/talent/api/v1/policy/page',
    '/talent/api/v1/project-vr/wx-login',
    "/yz/v1/building/parking",
    "/yz/v1/visitor/registration",
    "/talent/api/v1/invest-news/list",
    "/talent/api/v1/invest-news/one",
    "/talent/api/v1/invest-event/list",
    "/talent/api/v1/project-library/list",
    "/talent/api/v1/project-library/one",
    "/talent/api/v1/institution/list",
    "/talent/api/v1/institution/one",
    "/talent/api/v1/patent/page",
    "/talent/api/v1/patent/one",
    "/talent/api/v1/company/list",
    "/talent/api/v1/businesscard/list"
  ]

  for (let i = 0; i < tokenWhiteList.length; i += 1) {
    if (url.indexOf(tokenWhiteList[i]) > -1) return true
  }
  return false
}

function redirectLogin() {
  const instance = getCurrentInstance()
  const fromPath = Taro.getStorageSync('fromPath')
  if (!fromPath || (!fromPath.includes(instance.router.path) && !instance.router.path.includes(fromPath))) {
    Taro.setStorageSync('fromPath', instance.router.path)
  }
  return Taro.reLaunch({ url: '/pages/login/index' })
}

/**
 * HTTP 请求
 * @param options
 * @param refresh
 */
let isLoading = false
export default function request(options: Taro.request.Option, refresh = false): Promise<any> {
  const isShowloading = options.url.indexOf('/yz/v1/public/native_pushs?q=getUnreadNumber') === -1
  if (isShowloading && !isLoading) {
    isLoading = true
    Taro.showLoading({ title: '加载中...', mask: true })
  }
  return new Promise(async (resolve, reject) => {
    if (!inWhiteList(options.url)) {
      // 当前url 不需要token
      const token = Taro.getStorageSync('token')
      if (token) {
        options.header = { Authorization: `${token.token_type} ${token.access_token}` }
        if (!refresh) {
          // 如果不是刷新令牌的请求，需要检测令牌的有效性。
          if (token.expires_at > Date.now() / 1000) {
            // 令牌有效
            if (token.expires_at - LEAD_TIME < Date.now() / 1000) {
              // 需要续期
              const newToken = await refreshToken()
              if (newToken) {
                // 存储新令牌
                Taro.setStorageSync('token', newToken)
                options.header = { Authorization: `${newToken.token_type} ${newToken.access_token}` }
              }
            }
          } else {
            // 令牌过期，重新登录
            redirectLogin()
          }
        }
      } else {
        // 没有令牌，重新登录
        redirectLogin()
      }
    }
    // 请求成功后的回调
    options.success = (res) => {
      if (isShowloading && isLoading) {
        isLoading = false
        Taro.hideLoading()
      }
      const { data, statusCode } = res
      if (statusCode === 200) {
        resolve(data)
      } else {
        if (statusCode === 401) {
          const user_name = Taro.getStorageSync('userNames')
          Taro.setStorageSync('userNames', user_name)
          Taro.reLaunch({ url: '/pages/login/index' })
          Taro.showToast({ title: '会话超时', icon: 'none' })
        }
        reject(data)
      }
    }
    // 请求失败后的回调
    options.fail = (res) => {
      if (isShowloading && isLoading) {
        isLoading = false
        Taro.hideLoading()
      }
      reject(res)
    }
    options.url = concatWithBaseUrl(options.url)
    Taro.request(options)
  })
}

export async function refreshToken(): Promise<any> {
  return new Promise(async (resolve) => {
    request({ url: '/authx/auth/v1/refresh/token', method: 'GET' }, true)
      .then((res) => {
        if (res && res.expires_at > Date.now() / 1000) {
          resolve(res)
        } else {
          resolve(null)
        }
      })
      .then(() => {
        resolve(null)
      })
  })
}

/**
 * OPTIONS 请求
 * @param url
 * @param options
 */
export function OPTIONS(url: string, options?: object) {
  return request({ url, method: 'OPTIONS', ...options })
}

/**
 * GET 请求
 * @param url
 * @param params
 * @param options
 */
export function GET(url: string, params?: any, options?: object) {
  return request({ url, method: 'GET', data: params, ...options })
}

/**
 * POST 请求
 * @param url
 * @param data
 * @param options
 */
export function POST(url: string, data?: any, options?: object) {
  return request({ url, method: 'POST', data, ...options })
}

/**
 * PUT 请求
 * @param url
 * @param data
 * @param options
 */
export function PUT(url: string, data?: any, options?: object) {
  return request({ url, method: 'PUT', data, ...options })
}

/**
 * DELETE 请求
 * @param url
 * @param params
 * @param options
 */
export function DELETE(url: string, params?: any, options?: object) {
  return request({ url, method: 'DELETE', data: params, ...options })
}

/**
 * DELETE 请求
 * @param url
 * @param data
 * @param options
 */
export function TRACE(url: string, data?: any, options?: object) {
  return request({ url, method: 'TRACE', data, ...options })
}

export function Upload(file, reduce?): Promise<any> {
  return new Promise((resolve, reject) => {
    let header
    const token = Taro.getStorageSync('token')
    if (token && token.expires_at > Date.now() / 1000) {
      header = {
        Authorization: `${token.token_type} ${token.access_token}`
      }
    }
    const reqUrl = reduce ? `/api/v1/files?reduce=${reduce}` : '/yz/v1/file/upload'
    Taro.uploadFile({
      url: getServerUrls().baseUrl + reqUrl,
      filePath: file,
      header,
      name: 'data',

      success: (res) => {
        const { data, statusCode } = res
        if (statusCode === 200) {
          resolve(jsonParse(data))
        } else {
          reject(jsonParse(data))
        }
      },
      fail: (res) => {
        reject(res)
      }
    })
  })
}

// 删除文件
